package net.myspring.common.thymeleaf.function.expression;

import com.google.common.collect.Lists;
import net.myspring.BlogApplication;
import net.myspring.common.mybatis.domain.Pageable;
import net.myspring.common.mybatis.domain.Sort;
import net.myspring.common.utils.Collections3;
import net.myspring.common.utils.Const;
import net.myspring.common.utils.StringUtils;
import net.myspring.common.utils.ThreadLocalContext;
import net.myspring.middle.domain.Account;
import net.myspring.middle.domain.Department;
import net.myspring.middle.domain.Menu;
import net.myspring.middle.domain.Role;
import net.myspring.middle.mapper.AccountMapper;
import net.myspring.middle.mapper.DepartmentMapper;
import net.myspring.middle.mapper.MenuMapper;
import net.myspring.middle.mapper.RoleMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

public final class ThymeleafFunction {

    private final Logger logger = LoggerFactory.getLogger(ThymeleafFunction.class);

    private ApplicationContext applicationContext = BlogApplication.getApplicationContext();

    public Account getAccount(String id) {
        return id == null ? null : applicationContext.getBean(AccountMapper.class).findOne(id);
    }

    public Menu getMenu(String id) {
        return id == null ? null : applicationContext.getBean(MenuMapper.class).findOne(id);
    }

    public Role getRole(String id) {
        return id == null ? null : applicationContext.getBean(RoleMapper.class).findOne(id);
    }

    public List<Role> getRoles(String accountId){
        return accountId == null ? null : applicationContext.getBean(RoleMapper.class).findByAccountId(accountId);
    }

    public Department getDepartment(String id) {
        return id == null ? null : applicationContext.getBean(DepartmentMapper.class).findOne(id);
    }

    public String formatLocalDate(LocalDate localDate) {
        return localDate == null ? "" : localDate.format(DateTimeFormatter.ofPattern(Const.DateFormat.DATE.getValue()));
    }

    public Menu getMenuByCode(String pageCode) {
        return pageCode == null ? null : applicationContext.getBean(MenuMapper.class).findByCode(pageCode);
    }

    public String formatLocalDateTime(LocalDateTime localDateTime) {
        String string = "";
        if (localDateTime != null) {
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(Const.DateFormat.DATE_TIME.getValue());
            string = localDateTime.format(dateTimeFormatter);
        }
        return string;
    }

    public String getStaticFile(String url) {
        RedisTemplate<String, String> redisTemplate = (RedisTemplate<String, String>) BlogApplication.getApplicationContext().getBean("redisTemplate");
        String key = "STATIC_FILE_VERSION_" + url;
        String value = redisTemplate.opsForValue().get(key);
        if (StringUtils.isBlank(value)) {
            try {
                File file = ResourceUtils.getFile("src/main/resources/static" + url);
                Long lastModified = file.lastModified();
                if (lastModified != null) {
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyMMddHHmmss");
                    value = simpleDateFormat.format(lastModified);
                    redisTemplate.opsForValue().set(key, value, 1, TimeUnit.HOURS);
                }
            } catch (FileNotFoundException e) {
                logger.error("file not found:" + url);
            }
        }
        if (StringUtils.isNotBlank(value)) {
            url = url + "?version=" + value;
        }
        return url;
    }

    public String getPageInput(Pageable pageable) {
        StringBuilder sb = new StringBuilder();
        sb.append("<input type='hidden' name='searchFromPage' value='true'/>").append(Const.CharEnum.ENTER.getValue());
        sb.append("<input type='hidden' name='pageNumber'  value='").append(pageable.getPageNumber()).append("'/>").append(Const.CharEnum.ENTER.getValue());
        sb.append("<input type='hidden' name='pageSize'  value='").append(pageable.getPageSize()).append("'/>").append(Const.CharEnum.ENTER.getValue());
        Iterator<Sort.Order> iterator = pageable.getSort().iterator();
        Sort.Direction direction = Sort.Direction.DESC;
        while (iterator.hasNext()) {
            Sort.Order sortOrder = iterator.next();
            String order = sortOrder.getProperty() + ": " + sortOrder.getDirection().name();
            sb.append("<input type='hidden' name='order'  value='").append(order).append("'/>").append(Const.CharEnum.ENTER.getValue());
        }
        return sb.toString();
    }

    public List<Menu> getHistoryMenus(String pageCode) {
        int maxSize = 10;
        RedisTemplate<String, List<Menu>> redisTemplate = (RedisTemplate<String, List<Menu>>) applicationContext.getBean("redisTemplate");
        MenuMapper menuMapper = applicationContext.getBean(MenuMapper.class);
        String cacheName = "historyMenus_" + ThreadLocalContext.get().getAccount().getId();
        List<Menu> menus = redisTemplate.opsForValue().get(cacheName);
        if (Collections3.isEmpty(menus)) {
            menus = Lists.newArrayList();
        }
        Menu activeMenu = menuMapper.findByCode(pageCode);
        if (!menus.contains(activeMenu) && !"首页".equals(activeMenu.getName())) {
            menus.add(activeMenu);
        }
        if (menus.size() > maxSize) {
            menus = new ArrayList<Menu>(menus.subList(menus.size() - maxSize, menus.size()));
        }
        redisTemplate.opsForValue().set(cacheName, menus);
        return menus;
    }
}